#include "euleroperator.h"
#include <iostream>

#include "face.h"
#include "vertex.h"
#include "halfedge.h"
#include "loop.h"
#include "point.h"
#include "solid.h"
#include "edge.h"
#include "hedmodel.h"

EulerOperator::EulerOperator()
{


}
void EulerOperator::mvfs(HEDModel& _model, int s, int f, int v, double x, double y, double z)
{
	Solid* newsolid = new Solid(_model.getFirsts());
    _model.setFirsts( newsolid );
	Point* point = new Point(x, y, z);
	Face* newface = new Face(newsolid);
	Vertex* newvertex = new Vertex(point,newsolid);
	HalfEdge* newhe = new HalfEdge();
	Loop* newloop = new Loop(newface);

	newsolid->setSolidno(s);
	newface->setFaceno(f);
	newvertex->setVertexno(v);
	newloop->setLedg( newhe );
	newface->setFlout( newloop );
	newhe->setWloop(newloop);
	newhe->setNxt(newhe);
	newhe->setPrv(newhe);
	newhe->setVtx(newvertex);
	newhe->setEdg(NULL);


	std::cout << "\nEulerOperator::mvfs implementado. \n";
}


void EulerOperator::mev(HEDModel& _model, int s, int f1, int f2, int v1, int v2, int v3, int v4, double x, double y, double z)
{
	Solid* oldsolid = NULL;
	Face* oldface1 = NULL;
	Face* oldface2 = NULL;
	HalfEdge* he1 = NULL;
	HalfEdge* he2 = NULL;

	if((oldsolid = _model.getsolid(s)) == NULL)
	{
		std::cout << "mev: solid " << s << " not found. \n";
		//return(ERROR);
	}
	if( (oldface1 = _model.fface(oldsolid,f1)) == NULL)
	{
		std::cout << "mev: face " << f1 << " not found in solid " << s << ". \n";
		//return(ERROR);
	}
	if( (oldface2 = _model.fface(oldsolid,f2)) == NULL)
	{
		std::cout << "mev: face " << f2 << " not found in solid " << s << ". \n";
		//return(ERROR);
	}
	if( (he1 = _model.fhe(oldface1,v1, v2)) == NULL)
	{
		std::cout << "mev: edge " << v1 << " - " << v2 << " not found in face " << f1 << ". \n";
		//return(ERROR);
	}
	if( (he2 = _model.fhe(oldface2,v1, v3)) == NULL)
	{
		std::cout << "mev: edge " << v1 << " - " << v3 << " not found in face " << f2 << ". \n";
		//return(ERROR);
	}
	this->lmev(he1, he2, v4,  x,  y, z);
	//return(SUCCESS);

}
void EulerOperator::mef(HEDModel& _model, int s, int f1, int v1, int v2, int v3, int v4, int f2)
{
	Solid* oldsolid = NULL;
	Face* oldface1 = NULL;
	HalfEdge* he1 = NULL;
	HalfEdge* he2 = NULL;

	if((oldsolid = _model.getsolid(s)) == NULL)
	{
		std::cout << "mev: solid " << s << " not found. \n";
		//return(ERROR);
	}
	if( (oldface1 = _model.fface(oldsolid,f1)) == NULL)
	{
		std::cout << "mev: face " << f1 << " not found in solid " << s << ". \n";
		//return(ERROR);
	}
	if( (he1 = _model.fhe(oldface1,v1, v2)) == NULL)
	{
		std::cout << "mev: edge " << v1 << " - " << v2 << " not found in face " << f1 << ". \n";
		//return(ERROR);
	}
}

void EulerOperator::lmev(HalfEdge* he1, HalfEdge* he2, int v, double x, double y, double z)
{
	Loop* loop = he1->getLoop();

	Face* face = loop->getFace();

	Solid* solid = face->getSolid();

	Edge* newedge = new Edge(solid);

	Point* point = new Point(x,y,z);
	
	Vertex* newvertex = new Vertex(point,solid);
	
	newvertex->setVertexno(v);
	
	HalfEdge* he = he1;
	while(he != he2)
	{
		he->setVtx(newvertex);
		he = he->mate()->getNxt();
	}

  newedge->addhe(he2->getVtx(), he1, MINUS);  // BRABO 22/11/11 Inverti as linhas
	newedge->addhe(newvertex, he2, PLUS); // o metodo deve ser utilizado por meio de um objeto

	newvertex->setVedge(he2->getPrv());
	he2->getVtx()->setVedge(he2);
	


	std::cout << "EulerOperator::lmev implementado. \n";
}


Face* EulerOperator::lmef(HalfEdge* he1, HalfEdge* he2, int f)
{
	Loop* loop = he1->getLoop();

	Face* face = loop->getFace();

	Solid* solid = face->getSolid();

	Face* newface = new Face(solid);

	Edge* newedge = new Edge(solid);

	Loop* newloop = new Loop(newface);

	newface->setFaceno(f);
	newface->setFlout(loop);


	HalfEdge* he = he1;
	while(he != he2)
	{
		he->setWloop(newloop);
		he = he->getNxt();
	}

	HalfEdge* nhe1 = newedge->addhe(he2->getVtx(), he1, MINUS);
	HalfEdge* nhe2 = newedge->addhe(he1->getVtx(), he2, PLUS);

	nhe1->getPrv()->setNxt(nhe2);
	nhe2->getPrv()->setNxt(nhe1);
	HalfEdge* temp = nhe1->getPrv();
	nhe1->setPrv(nhe2->getPrv());
	nhe2->setPrv(temp);

	newloop->setLedg(nhe1);
	he2->getLoop()->setLedg(nhe2);

	return newface;

	std::cout << "EulerOperator::semv nao implementado. \n";
}


void EulerOperator::lkemr(HalfEdge* h1, HalfEdge* h2)
{
	
	register HalfEdge* h3,*h4;

	Loop* ol= h1->getLoop();
	
	Loop* nl = new Loop(ol->getFace());

	h3 = h1->getNxt();
	h1->setNxt(h2->getNxt());
	h2->getNxt()->setPrv(h1);
	h2->setNxt(h3);
	h3->setPrv(h2);

	h4 = h2;
	do
	{
		h4->setWloop(nl);
	}
	while((h4 = h4->getNxt()) != h2);
	//ol->setLedg(h3 = delhe(h1);
	//nl->setLedg(h4 = delhe(h2);
	

	
	//std::cout << "EulerOperator::semv nao implementado. \n";
}




